"""add owner to workspace

Revision ID: cd79614189ac
Revises: 32e629b17e2e
Create Date: 2019-07-10 11:04:00.497200

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm import relationship
import typing  # revision identifiers, used by Alembic.

NAMING_CONVENTION = {
    "ix": "ix_%(column_0_label)s",
    "uq": "uq__%(table_name)s__%(column_0_name)s",  # Unique constrains
    # for ck contraint.
    # "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s",
}

metadata = MetaData(naming_convention=NAMING_CONVENTION)
DeclarativeBase = declarative_base(metadata=metadata)

revision = "cd79614189ac"
down_revision = "7bd8ec4c7236"


class TemporaryRoles(DeclarativeBase):
    """temporary sqlalchemy object to help migration"""

    __tablename__ = "user_workspace"

    user_id = Column(Integer, nullable=False, default=None, primary_key=True)
    workspace_id = Column(
        Integer,
        ForeignKey("workspaces.workspace_id"),
        nullable=False,
        default=None,
        primary_key=True,
    )
    role = Column(Integer, nullable=False, default=0, primary_key=False)
    workspace = relationship("TemporaryWorkspaces", back_populates="roles")


class TemporaryUserGroup(DeclarativeBase):
    """temporary sqlalchemy object to help migration"""

    __tablename__ = "user_group"

    group_id = Column(Integer, primary_key=True)
    user_id = Column(Integer, primary_key=True)


class TemporaryWorkspaces(DeclarativeBase):
    """temporary sqlalchemy object to help migration"""

    __tablename__ = "workspaces"

    workspace_id = Column(Integer, primary_key=True)
    owner_id = Column(Integer, nullable=True)
    roles = relationship(
        "TemporaryRoles",
        remote_side=[TemporaryRoles.workspace_id],
        back_populates="workspace",
        order_by="TemporaryRoles.user_id",
    )

    @property
    def owner_id_role(self) -> typing.Optional[int]:
        for role in self.roles:
            if role.role == 8:
                return role.user_id
        return None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table("workspaces") as batch_op:
        batch_op.add_column(sa.Column("owner_id", sa.Integer(), nullable=True))
    # INFO - G.M - 2019-08-19 - add owner_id to all workspaces
    connection = op.get_bind()
    session = Session(bind=connection)
    # INFO - G.M - 2019-09-20 - get one tracim admin as fallback
    admin_user_id = (
        session.query(TemporaryUserGroup.user_id)
        .filter(TemporaryUserGroup.group_id == 3)
        .order_by(TemporaryUserGroup.user_id)
        .all()[0][0]
    )
    workspaces = session.query(TemporaryWorkspaces).join(TemporaryRoles, isouter=True)
    for workspace in workspaces:
        workspace.owner_id = workspace.owner_id_role or admin_user_id
        session.add(workspace)
    session.commit()
    # INFO - G.M - 2019-08-19 - make owner id not nullable
    with op.batch_alter_table("workspaces") as batch_op:
        batch_op.alter_column("owner_id", nullable=False, type_=Integer)
        batch_op.create_foreign_key(
            constraint_name="fk_workspaces_owner_id_users",
            referent_table="users",
            local_cols=["owner_id"],
            remote_cols=["user_id"],
        )


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table("workspaces") as batch_op:
        batch_op.drop_constraint("fk_workspaces_owner_id_users", type_="foreignkey")
        batch_op.drop_column("owner_id")
    # ### end Alembic commands ###
